package shaw.wifi.nohttp;

import shaw.wifi.NetworkSettingsTaskManager;
import shaw.wifi.network.ConnectionInformation;

public class NetworkSettingsEstablishConnectionTask extends NetworkSettingsNoHttpTask {
	@Override
	protected Integer doInBackground(ConnectionInformation... params) {
		if(!setupSocketConnection()) {
			NetworkSettingsTaskManager.get().clearTasks();
			return null;
		}
		
		boolean result = getSharedKey();
		if(result == false) {
			NetworkSettingsTaskManager.get().clearTasks();
		}
		return null;
	}
	public boolean getSharedKey() {
	//ask for the RSA key
		ShawWifiMessage msg = new ShawWifiMessage(1);
		msg.type = ShawWifiMessage.TYPE_ESTABLISHCONNECTION;
		msg.header[0] = "action";
		msg.data[0] = "requestkey".getBytes();
		if(!sendMessage(msg)) {
			return false; //cannot send message(error in sendMessage() method
		}
		publishProgress("Sent request for this session's RSA public key");
		
		//await the response, if no response, then die
		//(error message appears from the waitForMessage() call)
		ShawWifiMessage response = waitForMessage();
		if(response == null) {
			publishProgress("Got no response...");
			return false;
		}
		
		//check for the correct values in the response
		try {
			//should be an Network settings message
			if(response.type != ShawWifiMessage.TYPE_ESTABLISHCONNECTION) throw new UnexpectedMessageException("expected network settings message");
			
			//should have 2 headers
			if(response.length != 2) throw new UnexpectedMessageException("expected length 2");
			
			//which hold the exponent and the modulus for this session's RSA public key
			if(!response.header[0].equals("RSAEXP")) throw new UnexpectedMessageException("expected header RSAEXP " + response.header[0]);
			if(!response.header[1].equals("RSAMOD")) throw new UnexpectedMessageException("expected header RSAMOD " + response.header[1]);
			
			//update the task's encryption settings with the RSA key
			boolean set = encryption.setServerRSAKey(response.data[0], response.data[1]);
			if(set) {
				publishProgress("Got server's RSA key...");
			} else {
				publishProgress("Failed to retrieve key...");
				return false;
			}
		} catch(UnexpectedMessageException e) {
			e.printStackTrace();
			publishProgress("Received unexpected message from server, please make sure you have the most recent version of the application");
			return false;
		}
		
		//generate the shared secret we want to use
		encryption.generateSharedKey();
		byte[] sharedKeyCryptBytes = encryption.encryptRSA(encryption.getSharedKey());
		byte[] ivCryptBytes = encryption.encryptRSA(encryption.getIv());
		
		//we have the RSA key, we want to encrypt the shared key we are going to use to transmit the network info,
		//as well as our user identification
		msg = new ShawWifiMessage(3);
		msg.type = ShawWifiMessage.TYPE_ESTABLISHCONNECTION;
		msg.header[0] = "action";
		msg.data[0] = "setsecret".getBytes();
		msg.header[1] = "sharedkey";
		msg.data[1] = sharedKeyCryptBytes;
		msg.header[2] = "sharediv";
		msg.data[2] = ivCryptBytes;
		if(!sendMessage(msg)) {
			return false; //cannot send message, error in sendMessage() method
		}
		
		response = waitForCryptMessage();
		if(response == null) {
			publishProgress("Got no response...");
			return false;
		}
		
		//check for the correct values in the response
		try {
			//should be an Network settings message
			if(response.type != ShawWifiMessage.TYPE_ESTABLISHCONNECTION) throw new UnexpectedMessageException("expected network settings message");
			
			//should have 2 headers
			if(response.length != 1) throw new UnexpectedMessageException("expected length 1");
			
			//which hold the exponent and the modulus for this session's RSA public key
			if(!response.header[0].equals("OK")) throw new UnexpectedMessageException("expected header OK " + response.header[0]);
			
			//update the task's encryption settings with the RSA key
			if((new String(response.data[0]).equals("true"))) {
				publishProgress("Shared secret for encrypted communication established...");
				return true;
			} else {
				publishProgress("Shared secret not established...");
				return false;
			}
		} catch(UnexpectedMessageException e) {
			e.printStackTrace();
			publishProgress("Received unexpected message from server, please make sure you have the most recent version of the application");
			return false;
		}
	}
			
}
